/**
 * API工厂
 * 生成符合新架构的API处理器，统一依赖注入和错误处理
 */

import { ApiCall } from 'tsrpc';
import { ApiHelper, ApiErrorCode } from './ApiHelper';
import { createApiContext, ApiContext } from '../di/ServiceContainer';

/**
 * API处理器类型定义
 */
export type ApiHandler<TReq = any, TRes = any> = (
    call: ApiCall<TReq, TRes>,
    context: ApiContext
) => Promise<void>;

/**
 * API配置选项
 */
export interface ApiOptions {
    /** API名称，用于日志 */
    name?: string;
    /** 必需参数列表 */
    requiredParams?: string[];
    /** 是否需要玩家验证 */
    requirePlayer?: boolean;
    /** 是否需要在线验证 */
    requireOnline?: boolean;
    /** 自定义验证函数 */
    customValidation?: (call: ApiCall<any, any>, context: ApiContext) => Promise<boolean>;
    /** 是否启用性能监控 */
    enableMonitoring?: boolean;
    /** 超时时间（毫秒） */
    timeout?: number;
}

/**
 * API工厂类
 */
export class ApiFactory {
    /**
     * 创建标准化的API处理器
     * 自动处理依赖注入、参数验证、错误处理等
     */
    static createHandler<TReq = any, TRes = any>(
        handler: ApiHandler<TReq, TRes>,
        options: ApiOptions = {}
    ): (call: ApiCall<TReq, TRes>) => Promise<void> {
        
        return async (call: ApiCall<TReq, TRes>) => {
            const apiName = options.name || 'UnknownAPI';
            
            // 记录API调用
            if (options.enableMonitoring !== false) {
                ApiHelper.logApiCall(call, apiName);
            }
            
            // 超时处理
            if (options.timeout) {
                const timeoutPromise = new Promise<void>((_, reject) => {
                    setTimeout(() => reject(new Error('API调用超时')), options.timeout);
                });
                
                await Promise.race([
                    this.executeHandler(call, handler, options),
                    timeoutPromise
                ]);
            } else {
                await this.executeHandler(call, handler, options);
            }
        };
    }
    
    /**
     * 执行API处理器
     */
    private static async executeHandler<TReq, TRes>(
        call: ApiCall<TReq, TRes>,
        handler: ApiHandler<TReq, TRes>,
        options: ApiOptions
    ): Promise<void> {
        try {
            // 参数验证
            if (options.requiredParams && options.requiredParams.length > 0) {
                const validation = ApiHelper.validateRequired(call.req, options.requiredParams);
                if (!validation.isValid) {
                    ApiHelper.missingParams(call, validation.missing);
                    return;
                }
            }
            
            // 创建API上下文
            const context = createApiContext();
            
            // 玩家验证
            if (options.requirePlayer || options.requireOnline) {
                const playerValid = await this.validatePlayer(call, context, options);
                if (!playerValid) {
                    return; // 错误已在validatePlayer中处理
                }
            }
            
            // 自定义验证
            if (options.customValidation) {
                const isValid = await options.customValidation(call, context);
                if (!isValid) {
                    ApiHelper.error(call, ApiErrorCode.FORBIDDEN, '自定义验证失败');
                    return;
                }
            }
            
            // 执行业务逻辑
            await handler(call, context);
            
        } catch (error) {
            console.error(`API ${options.name || 'Unknown'} 执行错误:`, error);
            
            if (error instanceof Error) {
                // 根据错误类型进行分类处理
                if (error.message.includes('玩家不存在')) {
                    ApiHelper.playerNotFound(call);
                } else if (error.message.includes('未在线') || error.message.includes('离线')) {
                    ApiHelper.playerOffline(call);
                } else if (error.message.includes('参数')) {
                    ApiHelper.invalidParams(call, error.message);
                } else if (error.message.includes('权限') || error.message.includes('授权')) {
                    ApiHelper.unauthorized(call, error.message);
                } else if (error.message.includes('超时')) {
                    ApiHelper.error(call, 'REQUEST_TIMEOUT', error.message);
                } else {
                    ApiHelper.internalError(call, error.message, error);
                }
            } else {
                ApiHelper.internalError(call, '未知错误');
            }
        }
    }
    
    /**
     * 验证玩家状态
     */
    private static async validatePlayer<TReq, TRes>(
        call: ApiCall<TReq, TRes>,
        context: ApiContext,
        options: ApiOptions
    ): Promise<boolean> {
        // 从请求中获取玩家ID或账号
        const playerId = this.extractPlayerId(call.req);
        if (!playerId) {
            ApiHelper.missingParams(call, ['playerId', 'account', 'userId']);
            return false;
        }
        
        // 获取玩家
        const userManager = context.userManager;
        let player = userManager.getOnlinePlayer(playerId);
        
        // 如果需要玩家验证但玩家不存在
        if (options.requirePlayer && !player) {
            ApiHelper.playerNotFound(call, playerId);
            return false;
        }
        
        // 如果需要在线验证但玩家不在线
        if (options.requireOnline && !player) {
            ApiHelper.playerOffline(call, playerId);
            return false;
        }
        
        return true;
    }
    
    /**
     * 从请求中提取玩家ID
     */
    private static extractPlayerId(req: any): string | null {
        return req.playerId || req.account || req.userId || req.id || null;
    }
    
    /**
     * 创建简单的API处理器
     * 用于只需要基本功能的API
     */
    static createSimpleHandler<TReq = any, TRes = any>(
        handler: (req: TReq, context: ApiContext) => Promise<TRes> | TRes,
        options: Omit<ApiOptions, 'customValidation'> = {}
    ): (call: ApiCall<TReq, TRes>) => Promise<void> {
        
        return this.createHandler(async (call, context) => {
            const result = await handler(call.req, context);
            ApiHelper.success(call, result);
        }, options);
    }
    
    /**
     * 创建玩家相关的API处理器
     * 自动处理玩家验证和获取
     */
    static createPlayerHandler<TReq = any, TRes = any>(
        handler: (req: TReq, player: any, context: ApiContext) => Promise<TRes> | TRes,
        options: Omit<ApiOptions, 'requirePlayer' | 'requireOnline'> = {}
    ): (call: ApiCall<TReq, TRes>) => Promise<void> {
        
        return this.createHandler(async (call, context) => {
            const playerId = this.extractPlayerId(call.req);
            if (!playerId) {
                throw new Error('无法获取玩家ID');
            }
            
            const player = context.userManager.getOnlinePlayer(playerId);
            if (!player) {
                throw new Error('玩家不存在或未在线');
            }
            
            const result = await handler(call.req, player, context);
            ApiHelper.success(call, result);
        }, {
            ...options,
            requirePlayer: true,
            requireOnline: true
        });
    }
    
    /**
     * 创建带缓存的API处理器
     * 自动处理结果缓存
     */
    static createCachedHandler<TReq = any, TRes = any>(
        handler: ApiHandler<TReq, TRes>,
        cacheKeyGenerator: (req: TReq) => string,
        cacheTTL: number = 300000, // 5分钟默认缓存
        options: ApiOptions = {}
    ): (call: ApiCall<TReq, TRes>) => Promise<void> {
        
        return this.createHandler(async (call, context) => {
            const cacheKey = cacheKeyGenerator(call.req);
            
            // 尝试从缓存获取
            const cache = await context.getService('GlobalCache');
            const cached = cache.get(cacheKey);
            
            if (cached) {
                ApiHelper.success(call, cached);
                return;
            }
            
            // 执行原始处理器
            await handler(call, context);
            
            // 缓存结果（这里需要拦截call.succ）
            const originalSucc = call.succ.bind(call);
            call.succ = (res: TRes) => {
                cache.set(cacheKey, res, cacheTTL);
                originalSucc(res);
            };
        }, options);
    }
}

/**
 * API装饰器
 * 提供更简洁的API定义方式
 */
export function Api(options: ApiOptions = {}) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        
        descriptor.value = ApiFactory.createHandler(originalMethod, {
            name: options.name || `${target.constructor.name}.${propertyKey}`,
            ...options
        });
        
        return descriptor;
    };
}

/**
 * 玩家API装饰器
 */
export function PlayerApi(options: Omit<ApiOptions, 'requirePlayer' | 'requireOnline'> = {}) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        
        descriptor.value = ApiFactory.createPlayerHandler(originalMethod, {
            name: options.name || `${target.constructor.name}.${propertyKey}`,
            ...options
        });
        
        return descriptor;
    };
}

/**
 * 缓存API装饰器
 */
export function CachedApi(
    cacheKeyGenerator: (req: any) => string,
    cacheTTL: number = 300000,
    options: ApiOptions = {}
) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        
        descriptor.value = ApiFactory.createCachedHandler(
            originalMethod,
            cacheKeyGenerator,
            cacheTTL,
            {
                name: options.name || `${target.constructor.name}.${propertyKey}`,
                ...options
            }
        );
        
        return descriptor;
    };
}
